#ifndef _H_C_COROUTINE_IMPL_H_
#define _H_C_COROUTINE_IMPL_H_

#include "../typedefine.h"
#include "../threadpool.h"
#include "../collection.h"
#include "../promise.h"
#include <memory>
#include <functional>
#include <atomic>

namespace TB
{
	class CCoroutine;
	class CCoroutineGroupImpl;
	class CCoroutineTimerContext;

	class CCoroutineImpl
	{
	public:
		typedef void(*DSetCurCoroutine)(const std::shared_ptr<CCoroutine>&);
	public:
		CCoroutineImpl(const std::weak_ptr<CCoroutineGroupImpl>& poGroup, const std::weak_ptr<CThreadPool>& poThreadPool, DSetCurCoroutine cbSetCurCoroutine, bool bManualPool);
		~CCoroutineImpl();
		inline void Init(const std::weak_ptr<CCoroutine>& poCoroutine) { m_poCoroutine = poCoroutine; }
		inline UINT64 GetID() const { return m_qwID; }
		UINT32 Poll(bool bFromGroup);
		void Post(const std::function<void()>* pcbFunction, bool bFromGroup);

	private:
		friend class CCoroutine;
		static void _PollPerMilliSecondInThreadPool();
		static void _Wakeup(UINT64 qwWakeupTime, const std::weak_ptr<CCoroutineImpl>& poWeakPtr);
		void _WakeupOn(UINT64 qwWakeupTime);
		UINT32 _Poll();

	public:
		std::weak_ptr<CCoroutineImpl> m_poSelf;
		std::weak_ptr<CCoroutineGroupImpl> m_poGroup;
		std::shared_ptr<CMPSCSyncContext> m_poSyncContext;
		std::shared_ptr<CCoroutineTimerContext> m_poTimerContext;
		std::chrono::steady_clock::time_point m_oLastPollTime;
		std::weak_ptr<CThreadPool> m_poThreadPool;
		std::atomic<INT32> m_oSem = 0;
		std::atomic<INT32> m_oPollLock = 0;
		std::weak_ptr<CCoroutine> m_poCoroutine;
		DSetCurCoroutine m_cbSetCurCoroutine;
		UINT64 m_qwWakeupTime = 0;

	private:
		STimerUID m_sWakeupTimerUID;
		UINT64 m_qwID;
		bool m_bManualPoll;

	private:
		static CMPSCQueue<std::pair<UINT64, std::weak_ptr<CCoroutineImpl>>> m_oSetTimeoutQueue;
		static std::shared_ptr<CTimerMgr> m_poTimeoutTimeMgr;
		static std::once_flag m_oInitFlag;
		static std::atomic_uint64_t m_qwIncID;
		static CMPSCQueue<STimerUID> m_oDestoryTimerQueue;
	};
}

#endif
